import uuid
import copy
import re
from URL import URL

DEFAULT_ENCODING = "utf-8"
DEFAULT_CHARSET = DEFAULT_ENCODING


def from_requests_response(res, req_url):
    code = res.status_code
    msg = res.reason
    headers = res.headers
    body = res.content
    charset = res.encoding
    return Response(code, headers, body, req_url, msg, charset=charset)


class Response:
    def __init__(self, status_code=None, headers=None, body=None, req_url=None, msg='OK', id=None, time=0.2, charset=None):
        self._code = status_code
        self._headers = headers
        self._req_url = req_url
        self._body = None
        self._raw_body = body
        self._msg = msg
        self._time = time
        self._charset = charset
        self.id = id if id else uuid.uuid1()

    def set_id(self, id):
        self.id = id

    def get_id(self):
        return self.id

    def set_code(self, code):
        self._code = code

    def get_code(self):
        return self._code

    def set_url(self, url):
        self._req_url = url

    def get_url(self):
        return self._req_url

    def set_body(self, body):
        self._body = body

    def get_body(self):
        return self._body

    def get_cookies(self):
        if "set-cookie" in self._headers.keys():
            return self._headers["set-cookie"]
        else:
            return None

    def get_headers(self):
        return self._headers

    @property
    def headers(self):
        return self._headers

    @property
    def body(self):
        if self._code is None:
            return self._body
        if self._body is None:
            self._body, self._charset = self.__charset_handling()
        return self._body

    @property
    def charset(self):
        if self._code is None:
            return self._charset
        if self._charset is None:
            self._body, self._charset = self.__charset_handling()
        return self._charset

    def set_charset(self, charset):
        self._charset = charset

    def get_charset(self):
        return self._charset

    def get_lowercase_headers(self):
        return dict((k.lower(), v) for k, v in self._headers.iteritems())

    def __charset_handling(self):
        lowercase_headers = self.get_lowercase_headers()
        charset = self._charset
        rawbody = self._raw_body

        if charset != DEFAULT_CHARSET and lowercase_headers.has_key('content-type'):
            charset_mo = re.search('charset=\s*?([\w-]+)', lowercase_headers['content-type'])
            if charset_mo:
                charset = charset_mo.groups()[0].lower().strip()
            else:
                charset_mo = re.search('<meta.*?content=".*?charset=\s*?([\w-]+)".*?>', rawbody, re.IGNORECASE)
                if charset_mo:
                    charset = charset_mo.groups()[0].lower().strip()
                else:
                    try:
                        raise Exception
                    except:
                        charset = DEFAULT_CHARSET

            try:
                _body = unicode(rawbody, charset)
            except:
                charset = "gbk"
                try:
                    _body = unicode(rawbody, charset)
                except UnicodeDecodeError, e:
                    _body = rawbody
                    charset = "UNKNOWN"

        else:
            _body = unicode(rawbody, "utf-8", errors="ignore")

        return _body, charset

    def __str__(self):
        result_string = 'HTTP/1.1 ' + str(self._code) + ' ' + self._msg + '\r\n'
        if self.headers:
            result_string += '\r\n'.join(h + ":" + hv for h, hv in self.headers.items()) + '\r\n'
        if self.body:
            result_string += '\r\n' + self.body.encode("utf-8")
        return result_string

    def __repr__(self):
        vals = {'code': self._code, 'url': str(self.get_url()), 'id': self.id}
        return '<Response | %(code)s | %(url)s | %(id)s>' % vals